/**
 * 对表格的行、列进行合并 以cm开头的参数:表示按内容合并 以pm开头的参数:表示按行列号合并
 * 
 * @Purpose:做一个可用于报表展示的jquery-table插件
 * @Version:1.0 08/14 2013
 * @Requires: jquery-1.7.js
 * @Author:wang yahzou QQ:506526593
 * @param {Object}
 */

(function($) {
	// 看过jquery源码就可以发现$.fn就是$.prototype, 只是为了兼容早期版本的插件
	// 才保留了jQuery.prototype这个形式
	$.fn.mergeCell = function(options) {
		options = $.extend(
				{
					demo : null,
					head_rows : 3,
					head_cols : 1,
					cols : 13,
					qdata : {},
					cmrows : [ false, null, null ], // 按内容合并的行的范围
					cmcols : [ false, null, null ], // 按内容合并的列的范围
					pmerges : [],
					rowwraps : null,
					colwraps : null,
					colcss : null,
					colthreds : null,
					thredcolors : [ [ 60, 80, 90 ],
							[ '#56A8F4', '#FF9937', '#CE110F' ] ],
					evenodd : false,
					url : '',
					sum : 0,
					pagesize : 300,
					curpage : 1,
					highlight : false,
					threshold : [ [ 60, 80, 90 ], [ '#eee', '#ddd', '#aaa' ] ]
				}, options || {});

		// 确保返回的仍是个jquery对象
		return this.each(function() {
			rendtoolbar($(this), options);
			init($(this), options);
			// rendheaders($(this), options);
			// cellHighLight($(this), options);
			boundEvent($(this), options);

		});

	};

	// 初始化表格数据
	function init($table, options) {
		// $('tr:gt(' + Number(options.head_rows) + ')', $table).remove();
		// var log = log4javascript.getDefaultLogger();
		var data = $.extend('true', {
			pagesize : options.pagesize,
			curpage : options.curpage
		}, options.qdata);
		// log.info(data);
		if (options.url != '') {
			$.ajax({
				url : options.url,
				type : 'POST',
				dataType : "json",
				data : data,
				success : function(data) {
					// $('#data_sum').text(data.size);
					fillDatas($table, data.data, options);
				}
			})
		} else {
			if (options.demo != null) {
				fillDatas($table, options.demo, options);
			} else {
				rendrowcols($table, options);
			}
		}
	}

	/**
	 * 加入工具条
	 */
	function rendtoolbar($table, options) {
		var date = new Date();
		var toolbar = '<tr><td colspan="' + options.cols
				+ '" class="report_tool_bar"><ul>';
		toolbar += '<li class="report_tool_bar_l"><img src="export2.gif"/> </li></ul>';
		toolbar += '<li class="report_tool_bar_l"><a title="导出为PDF"><img src="pdf.gif"/></a></li>';
		toolbar += '<li class="report_tool_bar_l"><a title="导出为EXCEL"><img src="excel.gif"/></a></li>';
		toolbar += '<li class="report_tool_bar_r report_tool_bar_time">制表时间：2013-08-19 12:00';
		toolbar += '</td></tr>';
		$table.prepend(toolbar);
	}

	/**
	 * 加入状态条
	 */
	function rendStatBar($table, options) {
		var statbar = '<tr><td colspan="' + options.cols
				+ '" class="report_tool_bar"><ul>';
		statbar += '<li class="report_tool_bar_l"><a id="button_prev" title="向前翻页">上一页</a></li></ul>';
		statbar += '<li class="report_tool_bar_l"><span>|</span></li></ul>';
		statbar += '<li class="report_tool_bar_l"><a id="button_prev" title="向后翻页">下一页</a></li></ul>';
		statbar += '<li class="report_tool_bar_r report_tool_bar_time">显示  1-'
				+ options.sum + ' 条';
		statbar += '<li class="report_tool_bar_r report_tool_bar_time">共 '
				+ options.sum + ' 条数据,';
		statbar += '</td></tr>';

		//$table.append(statbar);
	}
	
	// 修改表头 表头默认会按行列合并
	function rendheaders($table, options) {
		// 改变行表头的颜色并做列合并
		$('tr:gt(0):lt(' + Number(options.head_rows) + ')', $table).each(
				function(index) {
					$(this).css('background', '#e8eff8');
					mergeColCell($(this), 0, options.cols);
					$('td', $(this)).css('font-weight', 'bold').css(
							'text-align', 'center');
				});

		// 对行表头做行合并
		for ( var i = 0; i < options.cols; i++) {
			mergeRowCell($table, i, null, options.head_rows);
		}

		// 改变列表头的颜色
		$('tr:gt(' + Number(options.head_rows) + '):lt('
						+ Number(options.sum) + ')', $table).each(
				function(index) {
					for ( var i = 0; i < options.head_cols; i++) {
						$('td:eq(' + i + ')', $(this)).each(
								function(jndex) {
									$(this).css('background', '#efefff').css(
											'text-align', 'center');
								})
					}
				});

		// 对列表头做行合并
		for ( var i = 0; i < options.head_cols; i++) {
			mergeRowCell($table, i, options.head_rows, null);
		}
	}

	// 按规则做行列合并操作
	function rendrowcols($table, options) {

		var sum = $('tr:gt(' + options.head_rows + ')', $table).size();
		options = $.extend('true', options, {
			sum : sum
		});

		var rows = options.cmrows;
		var cols = options.cmcols;
		var merges = options.pmerges;
		// 合并指定列的相同内容行 优先级高
		if (cols[0]) {
			for ( var i = (cols[1] || options.head_cols); i <= (cols[2] || options.cols); i++) {
				mergeRowCell($table, i, null, null);
			}
		}

		/**
		 * 合并指定行的相同内容列 优先级中
		 */
		if (rows[0] && !cols[0]) {
			for ( var i = (rows[1] || options.head_rows); i <= (rows[2] || $(
					'tr', $table).size()); i++) {
				mergeColCell($('tr:eq(' + i + ')', $table), options.head_cols,
						options.cols);
			}
		}

		/**
		 * 合并指定单元格 优先级低
		 */
		if (!cols[0] && !rows[0]) {
			for ( var i = 0; i < merges.length; i++) {
				mergeBlock($table, merges[i][0], merges[i][1], merges[i][2],
						merges[i][3]);
			}
		}

		/**
		 * 把某一行的td的内容用指定代码包裹
		 * 
		 */
		if (options.rowwraps != null) {
			var rowwraps = options.rowwraps;
			for ( var i = 0; i < rowwraps.length; i++) {
				$('td:gt(' + Number(options.head_cols - 1) + ')',
						$('tr:eq(' + rowwraps[i][0] + ')', $table)).each(
						function(index) {
							$('span', $(this)).wrap(rowwraps[i][1]);
						})
			}
		}

		/**
		 * 
		 * 把某一列td的内容用指定代码包裹
		 */
		if (options.colwraps != null) {
			var colwraps = options.colwraps;
			for ( var i = 0; i < colwraps.length; i++) {
				$('tr:gt(' + options.head_rows + ')', $table).each(
						function(index) {
							$tr = $(this);
							$('td:eq(' + colwraps[i][0] + ')', $tr)
									.each(
											function(jndex) {
												$('span', $(this)).wrap(
														colwraps[i][1]);
											})
						})
			}
		}
		
		/**
		 * 阀值判断并高亮显示
		 */
		if (options.colthreds != null) {
			var threads = options.colthreds;
			var colors = options.thredcolors;
			for ( var i = 0; i < threads.length; i++) {
				$('tr:gt(' + options.head_rows + ')', $table)
						.each(
								function(index) {
									var $tr = $(this);
									$('td:eq(' + threads[i] + ')', $tr)
											.each(
													function(jndex) {
														var cont = $('span',
																$(this)).html();
														if (!isNaN(cont)) {
															if (Number(cont) >= colors[0][0]
																	&& Number(cont) < colors[0][1]) {
																$(this)
																		.css(
																				'color',
																				colors[1][0])
																		.css(
																				'font-weight',
																				'bold');
															} else if (Number(cont) >= colors[0][1]
																	&& Number(cont) < colors[0][2]) {
																$(this)
																		.css(
																				'color',
																				colors[1][1])
																		.css(
																				'font-weight',
																				'bold');
															} else if (Number(cont) >= colors[0][2]) {
																$(this)
																		.css(
																				'color',
																				colors[1][2])
																		.css(
																				'font-weight',
																				'bold');
															}
														} else {
														}
													})
								})
			}
		}

		if (options.colcss != null) {
			var colcss = options.colcss;
			for ( var i = 0; i < colcss.length; i++) {
				$('tr:gt(' + options.head_rows + ')', $table).each(
						function(index) {
							$tr = $(this);
							$('td:eq(' + colcss[i][0] + ')', $tr).each(
									function(jndex) {
										$(this).addClass(colcss[i][1]);
									})
						})
			}
		}

		if (options.evenodd) {
			$('tr:gt(' + options.head_rows + '):odd', $table).each(
					function(index) {
						$(this).css('background', '#F0F0F0');
					})
		}

		rendheaders($table, options);

		rendStatBar($table, options);

		dispose($table);
	}

	// 绑定事件
	function boundEvent($table, options) {
		$('#button_prev').live('click', function() {
			if (Number(options.curpage) == 1) {
				$('#button_prev').attr('disabled', true);
				return false;
			}

			var cur = Number($('#current_page').text()) - 1;
			options = $.extend(true, options, {
				curpage : cur
			});
			init($table, options);

			$('#current_page').text(cur);

			rendrowcols($table, settings);
		});
		$('#button_next')
				.live(
						'click',
						function() {
							var cur = Number($('#current_page').text()) + 1;

							if (Number(options.pagesize)
									* Number(options.curpage) >= Number(options.sum)) {
								$('#button_next').attr('disabled', true);
								return false;
							}
							options = $.extend(true, options, {
								curpage : cur
							});
							init($table, options);
							$('#current_page').text(cur);
							rendrowcols($table, settings);
						});
		$("#button_size").live('change', function() {
			options = $.extend(true, options, {
				pagesize : $(this).val()
			});

			init($table, options);
			rendrowcols($table, settings);
		});
	}

	// 用数据填充表格
	function fillDatas($table, datas, options) {
		var str = '';
		for ( var one in datas) {
			str += '<tr>';
			for ( var key in datas[one]) {
				str += '<td><span>' + datas[one][key] + '</span></td>';
			}
			str += '</tr>';
		}
		$('tbody', $table).each(function(index) {
			$(this).append(str);
		});

		rendrowcols($table, options);
	}

	// 合并一个指标的区域
	function mergeBlock($table, row_s, row_e, col_s, col_e) {
		var mer_cont = '';
		var $block = $('td:eq(' + col_s + ')',
				$('tr:eq(' + row_s + ')', $table));

		$(
				'tr:gt(' + Number(row_s - 1) + '):lt('
						+ Number(row_e - row_s + 1) + ')', $table).each(
				function(x_index) {
					$tr = $(this);
					$(
							'td:gt(' + Number(col_s - 1) + '):lt('
									+ Number(col_e - col_s + 1) + ')', $tr)
							.each(function(y_index) {
								if (x_index == 0 && y_index == 0) {

								} else {
									$(this).hide();
									// $(this).css('background', '#dddddd');
								}
							});
				});

		$block.html('');
		$block.attr('rowspan', Number(row_e - row_s + 1));
		$block.attr('colspan', Number(col_e - col_s + 1));

	}

	// 合并内容相同的列
	function mergeColCell($tr, colBegin, colEnd) {

		$tr.data('col-content-c', '');
		// 存放单元格内容
		$tr.data('col-rowspan-c', 1);
		// 存放计算的rowspan值 默认为1
		$tr.data('col-td-c', $());
		// 存放发现的第一个与前一行比较结果不同td(jQuery封装过的), 默认一个"空"的jquery对象
		// alert(colBegin + '__' + colEnd);
		// colBegin = colBegin || Number(options.head_cols - 1);
		// colEnd = colEnd || options.cols;

		$('td:gt(' + colBegin + '):lt(' + colEnd + ')', $tr).each(
				function(index) {
					var tdcont = $(this).html();
					if ($tr.data('col-content-c') == '') {
						$tr.data('col-content-c', tdcont);
						$tr.data('col-td-c', $(this));
					} else {
						// alert($tr.data('col-content-c')+'_'+tdcont)
						if ($tr.data('col-content-c') == tdcont) {
							var colspan = $tr.data('col-rowspan-c') + 1;
							$tr.data('col-rowspan-c', colspan);
							// 值得注意的是 如果用了$td.remove()就会对其他列的处理造成影响
							$tr.data('col-td-c').attr('colspan',
									$tr.data('col-rowspan-c'));
							$(this).hide();
						} else {

							$tr.data('col-content-c', tdcont);
							$tr.data('col-rowspan-c', 1);
							$tr.data('col-td-c', $(this));
						}
					}
				});
	}

	// 如果对javascript的closure和scope概念比较清楚, 这是个插件内部使用的private方法
	// 具体可以参考本人前一篇随笔里介绍的那本书
	function mergeRowCell($table, colIndex, rowBegin, rowEnd) {

		$table.data('col-content', '');
		// 存放单元格内容
		$table.data('col-rowspan', 1);

		// 存放计算的rowspan值 默认为1
		$table.data('col-td', $());
		// 存放发现的第一个与前一行比较结果不同td(jQuery封装过的), 默认一个"空"的jquery对象

		// 要处理表格的总行数, 用于最后一行做特殊处理时进行判断之用

		// 我们对每一行数据进行"扫面"处理 关键是定位col-td, 和其对应的rowspan
		rowBegin = rowBegin || 0;
		rowEnd = rowEnd || $('tr', $table).size();
		$table.data('trNum', Number(rowEnd - rowBegin - 1));
		// alert(Number(rowEnd-rowBegin));
		// alert(rowBegin + '__' + rowEnd);

		$('tr:gt(' + Number(rowBegin) + '):lt(' + Number(rowEnd + 1) + ')',
				$table).each(
				function(index) {
					// $('tr', $table).each(function(index) {
					// td:eq中的colIndex即列索引
					var $td = $('td:eq(' + colIndex + ')', this);

					// 取出单元格的当前内容
					var currentContent = $td.html();

					// 第一次时走此分支
					if ($table.data('col-content') == '') {
						$table.data('col-content', currentContent);
						$table.data('col-td', $td);

					} else {
						// 上一行与当前行内容相同
						if ($table.data('col-content') == currentContent) {
							// 上一行与当前行内容相同则col-rowspan累加, 保存新值
							var rowspan = $table.data('col-rowspan') + 1;
							$table.data('col-rowspan', rowspan);
							// 值得注意的是 如果用了$td.remove()就会对其他列的处理造成影响
							$td.hide();

							// 最后一行的情况比较特殊一点
							// 比如最后2行 td中的内容是一样的,
							// 那么到最后一行就应该把此时的col-td里保存的td设置rowspan

							if (++index == $table.data('trNum'))
								$table.data('col-td').attr('rowspan',
										$table.data('col-rowspan')).css(
										'text-align', 'center');

						} else {// 上一行与当前行内容不同
							// col-rowspan默认为1, 如果统计出的col-rowspan没有变化, 不处理
							if ($table.data('col-rowspan') != 1) {
								$table.data('col-td').attr('rowspan',
										$table.data('col-rowspan')).css(
										'text-align', 'center');
							}
							// 保存第一次出现不同内容的td, 和其内容, 重置col-rowspan
							$table.data('col-td', $td);
							$table.data('col-content', $td.html());
							$table.data('col-rowspan', 1);
						}
					}
				});
	}

	// 隔行换色
	function rendCols($table, rowBegin) {
		$('tr:gt(' + rowBegin + '):odd', $table).each(function(index) {
			$(this).css('background', '#F0F0Ff');
		});
	}

	// 同样是个private函数 清理内存之用
	function dispose($table) {
		$table.removeData();
	}

})(jQuery);
